{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {
    "collapsed": true
   },
   "source": [
    "# Working with pandas in pandapower\n",
    "\n",
    "All data in pandapower is stored in pandas dataframes, which is why all functionalities that are implemented in pandas (http://pandas.pydata.org/) can be used with pandapower. pandas is a very powerful and widely used tool for data analysis.\n",
    "\n",
    "In the following we will present just a few of the many possibilities how builtin pandas functions can make your life easier when working in pandapower.\n",
    "\n",
    "This tutorial refers to pandas functionalities and how to use them with pandapower. If you have not worked with pandas before, this should give you a good overview of the relevant functionality. If you are already familiar with pandas, it might still refresh your memory, but maybe not provide new information."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We use the mv_oberrhein example from the pandapower networks package for this tutorial."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "#Import the pandapower and the networks module:\n",
    "import pandapower as pp\n",
    "import pandapower.networks as nw\n",
    "import pandas as pd\n",
    "\n",
    "#Import an example network:\n",
    "net = nw.mv_oberrhein()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Accessing and Setting Parameters\n",
    "\n",
    "You can accesss all parameters of one element with the .loc command:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "name                                  Line 4\n",
       "std_type        NA2XS2Y 1x185 RM/25 12/20 kV\n",
       "from_bus                                 239\n",
       "to_bus                                   236\n",
       "length_km                           0.381968\n",
       "r_ohm_per_km                           0.161\n",
       "x_ohm_per_km                           0.117\n",
       "c_nf_per_km                              273\n",
       "g_us_per_km                                0\n",
       "max_i_ka                               0.362\n",
       "df                                         1\n",
       "parallel                                   1\n",
       "type                                      cs\n",
       "in_service                              True\n",
       "Name: 4, dtype: object"
      ]
     },
     "execution_count": 2,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "#Detailed information about line 4\n",
    "net.line.loc[4]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Or one parameter of multiple elements:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "5    3.3028\n",
       "6    0.3504\n",
       "Name: length_km, dtype: float64"
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "#Length information about line 5 and 6\n",
    "net.line.length_km.loc[[5,6]]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The values are returned as a pandas series. To get them in an array instead, use the values function:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([3.3028, 0.3504])"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "#Length information about line 5 and 6 as numpy array\n",
    "net.line.length_km.loc[[5,6]].values"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Multiple parameters of multiple elements are returned as a pandas dataframe:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>length_km</th>\n",
       "      <th>r_ohm_per_km</th>\n",
       "      <th>x_ohm_per_km</th>\n",
       "      <th>c_nf_per_km</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>5</th>\n",
       "      <td>3.3028</td>\n",
       "      <td>0.161</td>\n",
       "      <td>0.117</td>\n",
       "      <td>273.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>6</th>\n",
       "      <td>0.3504</td>\n",
       "      <td>0.161</td>\n",
       "      <td>0.117</td>\n",
       "      <td>273.0</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "   length_km  r_ohm_per_km  x_ohm_per_km  c_nf_per_km\n",
       "5     3.3028         0.161         0.117        273.0\n",
       "6     0.3504         0.161         0.117        273.0"
      ]
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "#Length and type information about line 5 and 6                               \n",
    "net.line.loc[[5,6], [\"length_km\", \"r_ohm_per_km\", \"x_ohm_per_km\", \"c_nf_per_km\"]]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "collapsed": true
   },
   "source": [
    "The values function in this case yields a multi-dimensional array:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[3.3028e+00, 1.6100e-01, 1.1700e-01, 2.7300e+02],\n",
       "       [3.5040e-01, 1.6100e-01, 1.1700e-01, 2.7300e+02]])"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "#Length and type information about line 5 and 6  as an array                             \n",
    "net.line.loc[[5,6], [\"length_km\", \"r_ohm_per_km\", \"x_ohm_per_km\", \"c_nf_per_km\"]].values"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "To access exactly one parameter, .at can be used instead of .loc:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "0.3504"
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "net.line.length_km.at[6]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "This .at solution can only be used for exactly one parameter, but is siginifcantly faster than using .loc. That is why you should always use .at if possible!"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Setting parameters works the same way:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Line lengths after parameter setting:\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "4    1.8\n",
       "5    3.2\n",
       "6    2.2\n",
       "Name: length_km, dtype: float64"
      ]
     },
     "execution_count": 8,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "#Set single parameter with .at\n",
    "net.line.length_km.at[5] = 3.2\n",
    "#or\n",
    "net.line.at[5, \"length_km\"] = 3.2\n",
    "\n",
    "#Set multiple parameters with .loc\n",
    "net.line.length_km.loc[[4,6]] = [1.8, 2.2]\n",
    "\n",
    "#Output\n",
    "print(\"Line lengths after parameter setting:\")\n",
    "net.line.length_km.loc[[4,5,6]]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Statistical Evaluations\n",
    "\n",
    "You can easily find maximum, minimum values of a column with pandas, e.g."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Maximum Line Length: 3.20 km\n",
      "Minimum Line Length: 0.07 km\n",
      "Mean Line Length: 0.62 km\n"
     ]
    }
   ],
   "source": [
    "print(\"Maximum Line Length: %.2f km\"%net.line.length_km.max())\n",
    "print(\"Minimum Line Length: %.2f km\"%net.line.length_km.min())\n",
    "print(\"Mean Line Length: %.2f km\"%net.line.length_km.mean())"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Of course you can also combine these, for example to calculate weighted means:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Weighted Mean Resistance: 0.16 Ohm per kilometer\n"
     ]
    }
   ],
   "source": [
    "weighted_mean_r = (net.line.length_km * net.line.r_ohm_per_km).sum() / net.line.length_km.sum()\n",
    "print(\"Weighted Mean Resistance: %.2f Ohm per kilometer\"%weighted_mean_r)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Iterating over Elements\n",
    "\n",
    "If you want to iterate over a dataframe, use the iterrows function. It gives you the index of each row and the row as a pandas series."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "the line with index 4 is 1.800000 kilometers long and has a resistance of 0.161000 ohm per kilometers\n",
      "the line with index 5 is 3.200000 kilometers long and has a resistance of 0.161000 ohm per kilometers\n",
      "the line with index 6 is 2.200000 kilometers long and has a resistance of 0.161000 ohm per kilometers\n"
     ]
    }
   ],
   "source": [
    "for lidx, linerow in net.line.loc[[4,5,6]].iterrows():\n",
    "        print(\"the line with index %s is %f kilometers long and has a resistance of %f ohm per kilometers\" %(lidx, linerow.length_km, linerow.r_ohm_per_km))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "You can also group elements that share the same value in any column of the dataframe with the groubpy function of pandas;"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "there are 10 lines with standard type 243-AL1/39-ST1A 20.0 with an overall length of 10.761400 kilometers\n",
      "there are 160 lines with standard type NA2XS2Y 1x185 RM/25 12/20 kV with an overall length of 96.806343 kilometers\n",
      "there are 11 lines with standard type NA2XS2Y 1x240 RM/25 12/20 kV with an overall length of 4.343042 kilometers\n"
     ]
    }
   ],
   "source": [
    "for std_type, linetable in net.line.groupby(net.line.std_type):\n",
    "        print(\"there are %u lines with standard type %s with an overall length of %f kilometers\"%(len(linetable), std_type, linetable.length_km.sum()))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The first variable is now the value of the column you grouped by (here line standard type) and the second variable is a pandas dataframe of all lines that have this value (here all lines with the standard type defined in the first variable)."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "You can also directly sum up certain values of a groupby, for example"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "std_type\n",
       "243-AL1/39-ST1A 20.0            10.761400\n",
       "NA2XS2Y 1x185 RM/25 12/20 kV    96.806343\n",
       "NA2XS2Y 1x240 RM/25 12/20 kV     4.343042\n",
       "Name: length_km, dtype: float64"
      ]
     },
     "execution_count": 13,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "net.line.groupby(net.line.std_type).sum().length_km"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "gives you a pandas of series with the sum of all line length grouped by standard type."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Querying Dataframes\n",
    "\n",
    "You will often need to select elements with specific characteristics. You can do that with boolean masks:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [],
   "source": [
    "mask = net.line.length_km > 2.5"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "the mask variable is now a boolean time series that indicates for every line if it longer than 2500 meters or not. We can now select only the ones which are longer than 2500 meters and output their name and length:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>name</th>\n",
       "      <th>length_km</th>\n",
       "      <th>std_type</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>162</th>\n",
       "      <td>Line 162</td>\n",
       "      <td>2.595300</td>\n",
       "      <td>243-AL1/39-ST1A 20.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>45</th>\n",
       "      <td>Line 45</td>\n",
       "      <td>2.611111</td>\n",
       "      <td>NA2XS2Y 1x185 RM/25 12/20 kV</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>5</th>\n",
       "      <td>Line 5</td>\n",
       "      <td>3.200000</td>\n",
       "      <td>NA2XS2Y 1x185 RM/25 12/20 kV</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>59</th>\n",
       "      <td>Line 59</td>\n",
       "      <td>3.155390</td>\n",
       "      <td>NA2XS2Y 1x185 RM/25 12/20 kV</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>91</th>\n",
       "      <td>Line 91</td>\n",
       "      <td>2.528200</td>\n",
       "      <td>NA2XS2Y 1x185 RM/25 12/20 kV</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "         name  length_km                      std_type\n",
       "162  Line 162   2.595300          243-AL1/39-ST1A 20.0\n",
       "45    Line 45   2.611111  NA2XS2Y 1x185 RM/25 12/20 kV\n",
       "5      Line 5   3.200000  NA2XS2Y 1x185 RM/25 12/20 kV\n",
       "59    Line 59   3.155390  NA2XS2Y 1x185 RM/25 12/20 kV\n",
       "91    Line 91   2.528200  NA2XS2Y 1x185 RM/25 12/20 kV"
      ]
     },
     "execution_count": 15,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "long_lines = net.line[mask]\n",
    "\n",
    "#Output\n",
    "long_lines[[\"name\", \"length_km\", \"std_type\"]]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "or, directly in one step:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>name</th>\n",
       "      <th>length_km</th>\n",
       "      <th>std_type</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>162</th>\n",
       "      <td>Line 162</td>\n",
       "      <td>2.595300</td>\n",
       "      <td>243-AL1/39-ST1A 20.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>45</th>\n",
       "      <td>Line 45</td>\n",
       "      <td>2.611111</td>\n",
       "      <td>NA2XS2Y 1x185 RM/25 12/20 kV</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>5</th>\n",
       "      <td>Line 5</td>\n",
       "      <td>3.200000</td>\n",
       "      <td>NA2XS2Y 1x185 RM/25 12/20 kV</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>59</th>\n",
       "      <td>Line 59</td>\n",
       "      <td>3.155390</td>\n",
       "      <td>NA2XS2Y 1x185 RM/25 12/20 kV</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>91</th>\n",
       "      <td>Line 91</td>\n",
       "      <td>2.528200</td>\n",
       "      <td>NA2XS2Y 1x185 RM/25 12/20 kV</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "         name  length_km                      std_type\n",
       "162  Line 162   2.595300          243-AL1/39-ST1A 20.0\n",
       "45    Line 45   2.611111  NA2XS2Y 1x185 RM/25 12/20 kV\n",
       "5      Line 5   3.200000  NA2XS2Y 1x185 RM/25 12/20 kV\n",
       "59    Line 59   3.155390  NA2XS2Y 1x185 RM/25 12/20 kV\n",
       "91    Line 91   2.528200  NA2XS2Y 1x185 RM/25 12/20 kV"
      ]
     },
     "execution_count": 16,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "net.line[net.line.length_km > 2.5][[\"name\", \"length_km\", \"std_type\"]]\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "\n",
    "You can of course also check for exact values, for example if you want all 110 kV buses:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>name</th>\n",
       "      <th>vn_kv</th>\n",
       "      <th>type</th>\n",
       "      <th>zone</th>\n",
       "      <th>in_service</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>318</th>\n",
       "      <td>None</td>\n",
       "      <td>110.0</td>\n",
       "      <td>b</td>\n",
       "      <td>None</td>\n",
       "      <td>True</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>58</th>\n",
       "      <td>bus_250</td>\n",
       "      <td>110.0</td>\n",
       "      <td>n</td>\n",
       "      <td>None</td>\n",
       "      <td>True</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "        name  vn_kv type  zone  in_service\n",
       "318     None  110.0    b  None        True\n",
       "58   bus_250  110.0    n  None        True"
      ]
     },
     "execution_count": 17,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "net.bus[net.bus.vn_kv == 110]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "For string querys, use the str.contains function, for example to find loads with \"MV\" in the name:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>name</th>\n",
       "      <th>bus</th>\n",
       "      <th>p_mw</th>\n",
       "      <th>q_mvar</th>\n",
       "      <th>const_z_percent</th>\n",
       "      <th>const_i_percent</th>\n",
       "      <th>sn_mva</th>\n",
       "      <th>scaling</th>\n",
       "      <th>in_service</th>\n",
       "      <th>type</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>141</th>\n",
       "      <td>MV Load 0</td>\n",
       "      <td>215</td>\n",
       "      <td>0.5</td>\n",
       "      <td>0.101529</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>NaN</td>\n",
       "      <td>0.6</td>\n",
       "      <td>True</td>\n",
       "      <td>MV Load</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>142</th>\n",
       "      <td>MV Load 1</td>\n",
       "      <td>6</td>\n",
       "      <td>0.5</td>\n",
       "      <td>0.101529</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>NaN</td>\n",
       "      <td>0.6</td>\n",
       "      <td>True</td>\n",
       "      <td>MV Load</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>143</th>\n",
       "      <td>MV Load 2</td>\n",
       "      <td>48</td>\n",
       "      <td>0.5</td>\n",
       "      <td>0.101529</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>NaN</td>\n",
       "      <td>0.6</td>\n",
       "      <td>True</td>\n",
       "      <td>MV Load</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>144</th>\n",
       "      <td>MV Load 3</td>\n",
       "      <td>52</td>\n",
       "      <td>0.5</td>\n",
       "      <td>0.101529</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>NaN</td>\n",
       "      <td>0.6</td>\n",
       "      <td>True</td>\n",
       "      <td>MV Load</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>145</th>\n",
       "      <td>MV Load 4</td>\n",
       "      <td>55</td>\n",
       "      <td>0.5</td>\n",
       "      <td>0.101529</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>NaN</td>\n",
       "      <td>0.6</td>\n",
       "      <td>True</td>\n",
       "      <td>MV Load</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>146</th>\n",
       "      <td>MV Load 5</td>\n",
       "      <td>235</td>\n",
       "      <td>0.5</td>\n",
       "      <td>0.101529</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>NaN</td>\n",
       "      <td>0.6</td>\n",
       "      <td>True</td>\n",
       "      <td>MV Load</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "          name  bus  p_mw    q_mvar  const_z_percent  const_i_percent  sn_mva  \\\n",
       "141  MV Load 0  215   0.5  0.101529              0.0              0.0     NaN   \n",
       "142  MV Load 1    6   0.5  0.101529              0.0              0.0     NaN   \n",
       "143  MV Load 2   48   0.5  0.101529              0.0              0.0     NaN   \n",
       "144  MV Load 3   52   0.5  0.101529              0.0              0.0     NaN   \n",
       "145  MV Load 4   55   0.5  0.101529              0.0              0.0     NaN   \n",
       "146  MV Load 5  235   0.5  0.101529              0.0              0.0     NaN   \n",
       "\n",
       "     scaling  in_service     type  \n",
       "141      0.6        True  MV Load  \n",
       "142      0.6        True  MV Load  \n",
       "143      0.6        True  MV Load  \n",
       "144      0.6        True  MV Load  \n",
       "145      0.6        True  MV Load  \n",
       "146      0.6        True  MV Load  "
      ]
     },
     "execution_count": 18,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "net.load[net.load.name.str.startswith(\"MV\")]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "or to find all all loads that contain \"Load 0\" in their name:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>name</th>\n",
       "      <th>bus</th>\n",
       "      <th>p_mw</th>\n",
       "      <th>q_mvar</th>\n",
       "      <th>const_z_percent</th>\n",
       "      <th>const_i_percent</th>\n",
       "      <th>sn_mva</th>\n",
       "      <th>scaling</th>\n",
       "      <th>in_service</th>\n",
       "      <th>type</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>LV Load 0</td>\n",
       "      <td>103</td>\n",
       "      <td>0.25</td>\n",
       "      <td>0.050765</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>NaN</td>\n",
       "      <td>0.6</td>\n",
       "      <td>True</td>\n",
       "      <td>MV/LV Station</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>141</th>\n",
       "      <td>MV Load 0</td>\n",
       "      <td>215</td>\n",
       "      <td>0.50</td>\n",
       "      <td>0.101529</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>NaN</td>\n",
       "      <td>0.6</td>\n",
       "      <td>True</td>\n",
       "      <td>MV Load</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "          name  bus  p_mw    q_mvar  const_z_percent  const_i_percent  sn_mva  \\\n",
       "0    LV Load 0  103  0.25  0.050765              0.0              0.0     NaN   \n",
       "141  MV Load 0  215  0.50  0.101529              0.0              0.0     NaN   \n",
       "\n",
       "     scaling  in_service           type  \n",
       "0        0.6        True  MV/LV Station  \n",
       "141      0.6        True        MV Load  "
      ]
     },
     "execution_count": 19,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "net.load[net.load.name.str.contains(\"Load 0\")]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The isin function allows you to check if certain values are contained in a list, for example:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>name</th>\n",
       "      <th>from_bus</th>\n",
       "      <th>to_bus</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>165</th>\n",
       "      <td>Line 165</td>\n",
       "      <td>39</td>\n",
       "      <td>86</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "         name  from_bus  to_bus\n",
       "165  Line 165        39      86"
      ]
     },
     "execution_count": 21,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "lines = net.line[net.line.from_bus.isin([39,72])]\n",
    "lines[[\"name\", \"from_bus\", \"to_bus\"]]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "returns the names of all lines that are connected to one of the buses 39 or 72 at the from bus."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "You can also combine certain queries with the logical | (or) and & (and) for more complicated queries, for example:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>name</th>\n",
       "      <th>from_bus</th>\n",
       "      <th>to_bus</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>162</th>\n",
       "      <td>Line 162</td>\n",
       "      <td>80</td>\n",
       "      <td>39</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>165</th>\n",
       "      <td>Line 165</td>\n",
       "      <td>39</td>\n",
       "      <td>86</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>36</th>\n",
       "      <td>Line 36</td>\n",
       "      <td>289</td>\n",
       "      <td>72</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>54</th>\n",
       "      <td>Line 54</td>\n",
       "      <td>30</td>\n",
       "      <td>72</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "         name  from_bus  to_bus\n",
       "162  Line 162        80      39\n",
       "165  Line 165        39      86\n",
       "36    Line 36       289      72\n",
       "54    Line 54        30      72"
      ]
     },
     "execution_count": 22,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "lines = net.line[(net.line.from_bus.isin([39,72])) | (net.line.to_bus.isin([39,72]))]\n",
    "lines[[\"name\", \"from_bus\", \"to_bus\"]]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "returns the names of all lines that are connected to one of the buses 39 or 72 at the from bus or to bus."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Please be aware that the boolean query always returns a copy of the dataframe. Lets say you want to set all medium voltage nodes out of service and try this:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "metadata": {},
   "outputs": [],
   "source": [
    "net.bus[net.bus.vn_kv > 25].in_service = False"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "You will notice that your pandapower network table did not change:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "0      True\n",
       "1      True\n",
       "100    True\n",
       "101    True\n",
       "102    True\n",
       "Name: in_service, dtype: bool"
      ]
     },
     "execution_count": 24,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "net.bus.in_service.head()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "This is because the query returns a copy and you change the value in this copy in the same way like the following code:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0      False\n",
      "1      False\n",
      "100    False\n",
      "101    False\n",
      "102    False\n",
      "Name: in_service, dtype: bool\n",
      "0      True\n",
      "1      True\n",
      "100    True\n",
      "101    True\n",
      "102    True\n",
      "Name: in_service, dtype: bool\n"
     ]
    }
   ],
   "source": [
    "bus_table = net.bus[net.bus.vn_kv < 25]\n",
    "bus_table.in_service = False\n",
    "\n",
    "#Output\n",
    "print(bus_table.in_service.head())\n",
    "# but still:\n",
    "print(net.bus.in_service.head())"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Here bus_table is a copy of a part of the net.bus table. In the example above, you changed that copy, but not the original table. That is why you need to save the index of the copied bus table and than change the value of the original table:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0      False\n",
      "1      False\n",
      "100    False\n",
      "101    False\n",
      "102    False\n",
      "Name: in_service, dtype: bool\n"
     ]
    }
   ],
   "source": [
    "#Get index and store in ns_nodes\n",
    "ns_nodes = net.bus[net.bus.vn_kv < 25].index\n",
    "\n",
    "#Change all values where index is in ns_nodes\n",
    "net.bus.in_service.loc[ns_nodes] = False\n",
    "\n",
    "#Output\n",
    "print(net.bus.in_service.head())"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Extending and Customizing the Framework\n",
    "\n",
    "One of the benefits of pandapower is its easy to customize and extend datastructure. For pandapower to be able to run a loadflow, the standard parameters of the datastructure have to be defined. However, you can extend the pandapower datastructure any way you like."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Say you have network that is partitioned in three zones A, B and C: "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 37,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "0      A\n",
       "1      A\n",
       "100    A\n",
       "101    A\n",
       "102    A\n",
       "Name: zone, dtype: object"
      ]
     },
     "execution_count": 37,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "nr_buses = len(net.bus.index)\n",
    "net.bus.loc[net.bus.index[:nr_buses], \"zone\"] = \"A\"\n",
    "net.bus.loc[net.bus.index[nr_buses:], \"zone\"] = \"B\"\n",
    "net.bus.zone.head()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The goal is to apply a load scaling factor of 0.8 in Zone A and of 0.6 in Zone B:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 38,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>name</th>\n",
       "      <th>bus</th>\n",
       "      <th>p_mw</th>\n",
       "      <th>q_mvar</th>\n",
       "      <th>const_z_percent</th>\n",
       "      <th>const_i_percent</th>\n",
       "      <th>sn_mva</th>\n",
       "      <th>scaling</th>\n",
       "      <th>in_service</th>\n",
       "      <th>type</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>LV Load 0</td>\n",
       "      <td>103</td>\n",
       "      <td>0.25</td>\n",
       "      <td>0.050765</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>NaN</td>\n",
       "      <td>0.8</td>\n",
       "      <td>True</td>\n",
       "      <td>MV/LV Station</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>LV Load 1</td>\n",
       "      <td>174</td>\n",
       "      <td>0.63</td>\n",
       "      <td>0.127927</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>NaN</td>\n",
       "      <td>0.8</td>\n",
       "      <td>True</td>\n",
       "      <td>MV/LV Station</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>10</th>\n",
       "      <td>LV Load 10</td>\n",
       "      <td>149</td>\n",
       "      <td>0.25</td>\n",
       "      <td>0.050765</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>NaN</td>\n",
       "      <td>0.8</td>\n",
       "      <td>True</td>\n",
       "      <td>MV/LV Station</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>100</th>\n",
       "      <td>LV Load 100</td>\n",
       "      <td>200</td>\n",
       "      <td>0.25</td>\n",
       "      <td>0.050765</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>NaN</td>\n",
       "      <td>0.8</td>\n",
       "      <td>True</td>\n",
       "      <td>MV/LV Station</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>101</th>\n",
       "      <td>LV Load 101</td>\n",
       "      <td>8</td>\n",
       "      <td>0.40</td>\n",
       "      <td>0.081223</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>NaN</td>\n",
       "      <td>0.8</td>\n",
       "      <td>True</td>\n",
       "      <td>MV/LV Station</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "            name  bus  p_mw    q_mvar  const_z_percent  const_i_percent  \\\n",
       "0      LV Load 0  103  0.25  0.050765              0.0              0.0   \n",
       "1      LV Load 1  174  0.63  0.127927              0.0              0.0   \n",
       "10    LV Load 10  149  0.25  0.050765              0.0              0.0   \n",
       "100  LV Load 100  200  0.25  0.050765              0.0              0.0   \n",
       "101  LV Load 101    8  0.40  0.081223              0.0              0.0   \n",
       "\n",
       "     sn_mva  scaling  in_service           type  \n",
       "0       NaN      0.8        True  MV/LV Station  \n",
       "1       NaN      0.8        True  MV/LV Station  \n",
       "10      NaN      0.8        True  MV/LV Station  \n",
       "100     NaN      0.8        True  MV/LV Station  \n",
       "101     NaN      0.8        True  MV/LV Station  "
      ]
     },
     "execution_count": 38,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "for i, load in net.load.iterrows():\n",
    "    if net.bus.zone.at[load.bus] == \"A\":\n",
    "        net.load.scaling.at[i] = 0.8\n",
    "    elif net.bus.zone.at[load.bus] == \"B\":\n",
    "        net.load.scaling.at[i] = 0.6\n",
    "net.load.head(n=5)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "However, you could also extend the line table to include the zone of each line like this:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 39,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>name</th>\n",
       "      <th>bus</th>\n",
       "      <th>p_mw</th>\n",
       "      <th>q_mvar</th>\n",
       "      <th>const_z_percent</th>\n",
       "      <th>const_i_percent</th>\n",
       "      <th>sn_mva</th>\n",
       "      <th>scaling</th>\n",
       "      <th>in_service</th>\n",
       "      <th>type</th>\n",
       "      <th>zone</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>LV Load 0</td>\n",
       "      <td>103</td>\n",
       "      <td>0.25</td>\n",
       "      <td>0.050765</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>NaN</td>\n",
       "      <td>0.8</td>\n",
       "      <td>True</td>\n",
       "      <td>MV/LV Station</td>\n",
       "      <td>A</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>LV Load 1</td>\n",
       "      <td>174</td>\n",
       "      <td>0.63</td>\n",
       "      <td>0.127927</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>NaN</td>\n",
       "      <td>0.8</td>\n",
       "      <td>True</td>\n",
       "      <td>MV/LV Station</td>\n",
       "      <td>A</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>10</th>\n",
       "      <td>LV Load 10</td>\n",
       "      <td>149</td>\n",
       "      <td>0.25</td>\n",
       "      <td>0.050765</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>NaN</td>\n",
       "      <td>0.8</td>\n",
       "      <td>True</td>\n",
       "      <td>MV/LV Station</td>\n",
       "      <td>A</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>100</th>\n",
       "      <td>LV Load 100</td>\n",
       "      <td>200</td>\n",
       "      <td>0.25</td>\n",
       "      <td>0.050765</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>NaN</td>\n",
       "      <td>0.8</td>\n",
       "      <td>True</td>\n",
       "      <td>MV/LV Station</td>\n",
       "      <td>A</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>101</th>\n",
       "      <td>LV Load 101</td>\n",
       "      <td>8</td>\n",
       "      <td>0.40</td>\n",
       "      <td>0.081223</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>NaN</td>\n",
       "      <td>0.8</td>\n",
       "      <td>True</td>\n",
       "      <td>MV/LV Station</td>\n",
       "      <td>A</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "            name  bus  p_mw    q_mvar  const_z_percent  const_i_percent  \\\n",
       "0      LV Load 0  103  0.25  0.050765              0.0              0.0   \n",
       "1      LV Load 1  174  0.63  0.127927              0.0              0.0   \n",
       "10    LV Load 10  149  0.25  0.050765              0.0              0.0   \n",
       "100  LV Load 100  200  0.25  0.050765              0.0              0.0   \n",
       "101  LV Load 101    8  0.40  0.081223              0.0              0.0   \n",
       "\n",
       "     sn_mva  scaling  in_service           type zone  \n",
       "0       NaN      0.8        True  MV/LV Station    A  \n",
       "1       NaN      0.8        True  MV/LV Station    A  \n",
       "10      NaN      0.8        True  MV/LV Station    A  \n",
       "100     NaN      0.8        True  MV/LV Station    A  \n",
       "101     NaN      0.8        True  MV/LV Station    A  "
      ]
     },
     "execution_count": 39,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "net.scaling = 1.0 #reset\n",
    "net.load[\"zone\"] = net.bus.zone.loc[net.load.bus.values].values\n",
    "net.load.head(n=5)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "and then apply your function only to the lines in Zone A:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 40,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>name</th>\n",
       "      <th>bus</th>\n",
       "      <th>p_mw</th>\n",
       "      <th>q_mvar</th>\n",
       "      <th>const_z_percent</th>\n",
       "      <th>const_i_percent</th>\n",
       "      <th>sn_mva</th>\n",
       "      <th>scaling</th>\n",
       "      <th>in_service</th>\n",
       "      <th>type</th>\n",
       "      <th>zone</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>LV Load 0</td>\n",
       "      <td>103</td>\n",
       "      <td>0.25</td>\n",
       "      <td>0.050765</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>NaN</td>\n",
       "      <td>0.8</td>\n",
       "      <td>True</td>\n",
       "      <td>MV/LV Station</td>\n",
       "      <td>A</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>LV Load 1</td>\n",
       "      <td>174</td>\n",
       "      <td>0.63</td>\n",
       "      <td>0.127927</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>NaN</td>\n",
       "      <td>0.8</td>\n",
       "      <td>True</td>\n",
       "      <td>MV/LV Station</td>\n",
       "      <td>A</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>10</th>\n",
       "      <td>LV Load 10</td>\n",
       "      <td>149</td>\n",
       "      <td>0.25</td>\n",
       "      <td>0.050765</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>NaN</td>\n",
       "      <td>0.8</td>\n",
       "      <td>True</td>\n",
       "      <td>MV/LV Station</td>\n",
       "      <td>A</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>100</th>\n",
       "      <td>LV Load 100</td>\n",
       "      <td>200</td>\n",
       "      <td>0.25</td>\n",
       "      <td>0.050765</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>NaN</td>\n",
       "      <td>0.8</td>\n",
       "      <td>True</td>\n",
       "      <td>MV/LV Station</td>\n",
       "      <td>A</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>101</th>\n",
       "      <td>LV Load 101</td>\n",
       "      <td>8</td>\n",
       "      <td>0.40</td>\n",
       "      <td>0.081223</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>NaN</td>\n",
       "      <td>0.8</td>\n",
       "      <td>True</td>\n",
       "      <td>MV/LV Station</td>\n",
       "      <td>A</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "            name  bus  p_mw    q_mvar  const_z_percent  const_i_percent  \\\n",
       "0      LV Load 0  103  0.25  0.050765              0.0              0.0   \n",
       "1      LV Load 1  174  0.63  0.127927              0.0              0.0   \n",
       "10    LV Load 10  149  0.25  0.050765              0.0              0.0   \n",
       "100  LV Load 100  200  0.25  0.050765              0.0              0.0   \n",
       "101  LV Load 101    8  0.40  0.081223              0.0              0.0   \n",
       "\n",
       "     sn_mva  scaling  in_service           type zone  \n",
       "0       NaN      0.8        True  MV/LV Station    A  \n",
       "1       NaN      0.8        True  MV/LV Station    A  \n",
       "10      NaN      0.8        True  MV/LV Station    A  \n",
       "100     NaN      0.8        True  MV/LV Station    A  \n",
       "101     NaN      0.8        True  MV/LV Station    A  "
      ]
     },
     "execution_count": 40,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "net.load.loc[net.load[net.load.zone==\"A\"].index, \"scaling\"] = 0.8\n",
    "net.load.loc[net.load[net.load.zone==\"B\"].index, \"scaling\"] = 0.6\n",
    "net.load.head(n=5)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Of course for this simple example, the first solution would also be feasible. But the more complicated your code gets, the more important it is to customize the pandapower framework, so your code is more efficient as well as easier to read and debug."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Merging Dataframes\n",
    "\n",
    "Lets say you want to see the voltage at each bus together with the bus name. The voltage is stored in net.res_bus, whereas the name ist stored in net.bus. The two values are in different tables, but they have the same index, which is why you can easily merge them into a new shared dataframe:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 41,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>name</th>\n",
       "      <th>vm_pu</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>bus_200</td>\n",
       "      <td>1.009473</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>bus_204</td>\n",
       "      <td>1.009354</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>100</th>\n",
       "      <td>bus_124</td>\n",
       "      <td>0.985973</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>101</th>\n",
       "      <td>bus_227</td>\n",
       "      <td>1.016048</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>102</th>\n",
       "      <td>bus_125</td>\n",
       "      <td>0.986398</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>103</th>\n",
       "      <td>bus_228</td>\n",
       "      <td>1.010983</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>104</th>\n",
       "      <td>bus_225</td>\n",
       "      <td>1.009973</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>106</th>\n",
       "      <td>bus_226</td>\n",
       "      <td>1.009925</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "        name     vm_pu\n",
       "0    bus_200  1.009473\n",
       "1    bus_204  1.009354\n",
       "100  bus_124  0.985973\n",
       "101  bus_227  1.016048\n",
       "102  bus_125  0.986398\n",
       "103  bus_228  1.010983\n",
       "104  bus_225  1.009973\n",
       "106  bus_226  1.009925"
      ]
     },
     "execution_count": 41,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "net = nw.mv_oberrhein()\n",
    "pp.runpp(net) #Run a load flow calculation to get result tables\n",
    "\n",
    "#Store bus name with bus voltage result of loadflow calculation in bus_results\n",
    "#axis={horizontal=0, vertical=1}: axis to concatenate along\n",
    "bus_results = pd.concat([net.bus.name, net.res_bus.vm_pu], axis=1)\n",
    "\n",
    "#Output\n",
    "bus_results.head(n=8)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Now bus results shows you the name and the voltage of each bus in one dataframe."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "If you want to see the bus voltage of all loads, you can also merge the bus and the load dataframe. They do not share an index, but rather the index of the bus is given in the “bus” column of the load table. In that case you can merge the dataframes like this: (for more information about the arguments see [pandas merging documentation] [pandas_merg])\n",
    "[pandas_merg]: http://pandas.pydata.org/pandas-docs/stable/merging.html "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 42,
   "metadata": {
    "scrolled": false
   },
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>vm_pu</th>\n",
       "      <th>va_degree</th>\n",
       "      <th>p_mw_x</th>\n",
       "      <th>q_mvar_x</th>\n",
       "      <th>name</th>\n",
       "      <th>bus</th>\n",
       "      <th>p_mw_y</th>\n",
       "      <th>q_mvar_y</th>\n",
       "      <th>const_z_percent</th>\n",
       "      <th>const_i_percent</th>\n",
       "      <th>sn_mva</th>\n",
       "      <th>scaling</th>\n",
       "      <th>in_service</th>\n",
       "      <th>type</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>67</th>\n",
       "      <td>1.009473</td>\n",
       "      <td>-6.778921</td>\n",
       "      <td>0.240</td>\n",
       "      <td>0.048734</td>\n",
       "      <td>LV Load 67</td>\n",
       "      <td>0</td>\n",
       "      <td>0.40</td>\n",
       "      <td>0.081223</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>NaN</td>\n",
       "      <td>0.6</td>\n",
       "      <td>True</td>\n",
       "      <td>MV/LV Station</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>17</th>\n",
       "      <td>1.009354</td>\n",
       "      <td>-6.783526</td>\n",
       "      <td>0.150</td>\n",
       "      <td>0.030459</td>\n",
       "      <td>LV Load 17</td>\n",
       "      <td>1</td>\n",
       "      <td>0.25</td>\n",
       "      <td>0.050765</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>NaN</td>\n",
       "      <td>0.6</td>\n",
       "      <td>True</td>\n",
       "      <td>MV/LV Station</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>25</th>\n",
       "      <td>0.985973</td>\n",
       "      <td>-5.642008</td>\n",
       "      <td>0.378</td>\n",
       "      <td>0.076756</td>\n",
       "      <td>LV Load 25</td>\n",
       "      <td>100</td>\n",
       "      <td>0.63</td>\n",
       "      <td>0.127927</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>NaN</td>\n",
       "      <td>0.6</td>\n",
       "      <td>True</td>\n",
       "      <td>MV/LV Station</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>92</th>\n",
       "      <td>1.016048</td>\n",
       "      <td>-6.052000</td>\n",
       "      <td>0.240</td>\n",
       "      <td>0.048734</td>\n",
       "      <td>LV Load 92</td>\n",
       "      <td>101</td>\n",
       "      <td>0.40</td>\n",
       "      <td>0.081223</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>NaN</td>\n",
       "      <td>0.6</td>\n",
       "      <td>True</td>\n",
       "      <td>MV/LV Station</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>81</th>\n",
       "      <td>0.986398</td>\n",
       "      <td>-5.628502</td>\n",
       "      <td>0.378</td>\n",
       "      <td>0.076756</td>\n",
       "      <td>LV Load 81</td>\n",
       "      <td>102</td>\n",
       "      <td>0.63</td>\n",
       "      <td>0.127927</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>NaN</td>\n",
       "      <td>0.6</td>\n",
       "      <td>True</td>\n",
       "      <td>MV/LV Station</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>1.010983</td>\n",
       "      <td>-6.234283</td>\n",
       "      <td>0.150</td>\n",
       "      <td>0.030459</td>\n",
       "      <td>LV Load 0</td>\n",
       "      <td>103</td>\n",
       "      <td>0.25</td>\n",
       "      <td>0.050765</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>NaN</td>\n",
       "      <td>0.6</td>\n",
       "      <td>True</td>\n",
       "      <td>MV/LV Station</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>14</th>\n",
       "      <td>1.009925</td>\n",
       "      <td>-6.271018</td>\n",
       "      <td>0.378</td>\n",
       "      <td>0.076756</td>\n",
       "      <td>LV Load 14</td>\n",
       "      <td>106</td>\n",
       "      <td>0.63</td>\n",
       "      <td>0.127927</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>NaN</td>\n",
       "      <td>0.6</td>\n",
       "      <td>True</td>\n",
       "      <td>MV/LV Station</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>116</th>\n",
       "      <td>0.985547</td>\n",
       "      <td>-5.655840</td>\n",
       "      <td>0.150</td>\n",
       "      <td>0.030459</td>\n",
       "      <td>LV Load 116</td>\n",
       "      <td>107</td>\n",
       "      <td>0.25</td>\n",
       "      <td>0.050765</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>NaN</td>\n",
       "      <td>0.6</td>\n",
       "      <td>True</td>\n",
       "      <td>MV/LV Station</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "        vm_pu  va_degree  p_mw_x  q_mvar_x         name  bus  p_mw_y  \\\n",
       "67   1.009473  -6.778921   0.240  0.048734   LV Load 67    0    0.40   \n",
       "17   1.009354  -6.783526   0.150  0.030459   LV Load 17    1    0.25   \n",
       "25   0.985973  -5.642008   0.378  0.076756   LV Load 25  100    0.63   \n",
       "92   1.016048  -6.052000   0.240  0.048734   LV Load 92  101    0.40   \n",
       "81   0.986398  -5.628502   0.378  0.076756   LV Load 81  102    0.63   \n",
       "0    1.010983  -6.234283   0.150  0.030459    LV Load 0  103    0.25   \n",
       "14   1.009925  -6.271018   0.378  0.076756   LV Load 14  106    0.63   \n",
       "116  0.985547  -5.655840   0.150  0.030459  LV Load 116  107    0.25   \n",
       "\n",
       "     q_mvar_y  const_z_percent  const_i_percent  sn_mva  scaling  in_service  \\\n",
       "67   0.081223              0.0              0.0     NaN      0.6        True   \n",
       "17   0.050765              0.0              0.0     NaN      0.6        True   \n",
       "25   0.127927              0.0              0.0     NaN      0.6        True   \n",
       "92   0.081223              0.0              0.0     NaN      0.6        True   \n",
       "81   0.127927              0.0              0.0     NaN      0.6        True   \n",
       "0    0.050765              0.0              0.0     NaN      0.6        True   \n",
       "14   0.127927              0.0              0.0     NaN      0.6        True   \n",
       "116  0.050765              0.0              0.0     NaN      0.6        True   \n",
       "\n",
       "              type  \n",
       "67   MV/LV Station  \n",
       "17   MV/LV Station  \n",
       "25   MV/LV Station  \n",
       "92   MV/LV Station  \n",
       "81   MV/LV Station  \n",
       "0    MV/LV Station  \n",
       "14   MV/LV Station  \n",
       "116  MV/LV Station  "
      ]
     },
     "execution_count": 42,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "load_bus_results = pd.merge(net.res_bus, net.load, left_index=True, right_on=\"bus\")\n",
    "\n",
    "#Output\n",
    "load_bus_results.head(n=8)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Here net.res_bus is the left and net.load is the right dataframe. To merge the dataframe into one, the index of the left dataframe (left_index=True) and the bus column of the right dataframe (right_on=”bus”) are used. The resulting dataframe shows you the load table with the bus results of the respective load buses."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "If you want to know the maximum voltage at a bus that has a load connected to it, you could use:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 43,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "1.0235513513299228"
      ]
     },
     "execution_count": 43,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "max_load_voltage = pd.merge(net.res_bus, net.load, left_index=True, right_on=\"bus\").vm_pu.max()\n",
    "\n",
    "#Output\n",
    "max_load_voltage"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "or alternatively with a boolean mask:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 44,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "1.0235513513299228"
      ]
     },
     "execution_count": 44,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "max_load_voltage = net.res_bus[net.bus.index.isin(net.load.bus.values)].vm_pu.max()\n",
    "\n",
    "#Output\n",
    "max_load_voltage"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "In this simple case, the boolean mask solution is about 5 times faster than merging the dataframes, so only use merging for more complicated operations or if runtime is not important (e.g. debugging)."
   ]
  }
 ],
 "metadata": {
  "anaconda-cloud": {},
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.5"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 1
}
